package light.head.dao.inv;

import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Map;

import light.head.cache.BCache;
import light.head.constant.Parm;
import light.head.constant.Sys;
import light.head.enm.RESULT;
import light.head.framework.base.BaseDAO;
import light.head.framework.entity.PageBean;
import light.head.framework.utils.DateUtils;
import light.head.model.inv.InvBillCode;
import light.head.model.inv.InvBillCodeConfig;

import org.springframework.stereotype.Service;

/**
 * 单据生成配置
 * @author yangguanghe @date 2014-6-17 @time 下午3:35:54
 *
 */

@Service
public class InvBillConfingDAO extends BaseDAO<InvBillCodeConfig, Integer> {
	
	
	private final static String minus = "-";
	// 对应业务的默认值：1.进货订单，2.销货订单，3.入库单，4.出库，5.收款单，6.付款单，7.调拨单，8.零售单，9.零售退货单，10.销货退货，11.进货退货
	
	private final static String sql_upd = "UPDATE InvBillCode  SET ymd = ?, number = ?  WHERE code = ?";
	private final static String sql_getByOc = "FROM InvBillCodeConfig b WHERE b.oc = ? AND b.deleted = 0";
	private final static String sql_createBillCode = "SELECT b.head, b.body, b.foot, c.ymd, c.number, b.code as bcode, c.code as ccode, c.btype, b.oc FROM InvBillCodeConfig b JOIN InvBillCode c ON b.code = c.bcc WHERE b.oc = ? AND c.btype = ? AND b.deleted = 0";
	
	public InvBillConfingDAO () {
	}
	
	/**
	 * 查询
	 *@param oc		机构编号
	 *@param pb		分页信息
	 *@param map	查询条件
	 *@author yangguanghe [2014-6-17_下午3:41:44]
	 */
	public RESULT findByMap(Integer oc, PageBean pb, Map<String, String> map) {
		if (null == oc) return RESULT.PARAMETER_ERROR;
		
		StringBuffer hql = new StringBuffer(" FROM InvBillCodeConfig b WHERE b.oc = ?");
		
		List<Object> parm = new ArrayList<Object>();
		parm.add(oc);
		
		if (null != map) {
			String head = map.get(Parm.HEAD);
			String body = map.get(Parm.BODY);
			String foot = map.get(Parm.FOOT);
			
			if (isNotNull(head)) {
				hql.append(" AND b.head LIKE ?");
				parm.add("%" + head + "%");
			}
			if (isNotNull(body)) {
				hql.append(" AND b.body LIKE ?");
				parm.add("%" + body + "%");
			}
			if (isNotNull(foot)) {
				hql.append(" AND b.foot LIKE ?");
				parm.add("%" + foot + "%");
			}
		}
		hql.append(" ORDER BY b.code DESC");
		return findToPageBean(hql.toString(), pb, parm);
	}
	
	/**
	 * 更新
	 *@param b		更新的对象参数
	 *@author yangguanghe [2014-6-17_下午4:06:04]
	 */
	public RESULT update(InvBillCodeConfig b) {
		
		if (null == b || null == b.getCode()) return RESULT.PARAMETER_ERROR;
		
		InvBillCodeConfig db = super.get(b.getCode());
		
		if (null == db) return RESULT.NOT_FIND;
		boolean ok = false;
		
		if (!isNotNull(db.getHead()) || (isNotNull(b.getHead()) && !b.getHead().equals(db.getHead()))) {
			db.setHead(b.getHead());
			ok = true;
		}
		if (!isNotNull(db.getBody()) || (isNotNull(b.getBody()) && !b.getBody().equals(db.getBody()))) {
			db.setBody(b.getBody());
			ok = true;
		}
		if (!isNotNull(db.getFoot()) || (isNotNull(b.getFoot()) && !b.getFoot().equals(db.getFoot()))) {
			db.setFoot(b.getFoot());
			ok = true;
		}
		
		if (null == db.getDeleted() || (null != b.getDeleted() && b.getDeleted().booleanValue() != db.getDeleted().booleanValue())) {
			ok = true;
			db.setDeleted(b.getDeleted());
		}
		
		if (ok) {
			return super.upd(db);
		}
		
		return RESULT.SUCCESS;
	}
	
	/**
	 * 通过机构编号获取对应的的单据配置
	 *@param oc		机构编号(一般为根机构编号)
	 *@param btype	业务单据类型(1.进货订单，2.销货订单，3.入库单，4.出库，5.收款单，6.付款单，7.调拨单，8.零售单，9.零售退货单，10.销货退货，11.进货退货)
	 *@author yangguanghe [2014-6-18_上午10:29:01]
	 */
	private InvBillCodeConfig getByOc(Integer oc) {
		if (null == oc) return null;
		return (InvBillCodeConfig) get(sql_getByOc, oc);
	}
	
	
	
	/**
	 * 通过业务类型获取对应的默认业务配置
	 * @param btype 业务类型
	 *@author yangguanghe [2014-6-19_下午2:58:45]
	 */
	private String getBuessByBtype (Byte btype) {
		//1.进货订单，2.销货订单，3.入库单，4.出库，5.收款单，6.付款单，7.调拨单，8.零售单，9.零售退货单，10.销货退货，11.进货退货
		if (null == btype) return null;
		String buess = BCache.bTypes.get(btype.toString());
		if (null == buess)
			System.out.println("没有对应的业务类型配置");
		return buess;
	}
	
	
	/**
	 * 生成单据编号 格式: JKQ-20140703026865650001
	 *@param oc		机构编号（一搬为跟机构编号）
	 *@param btype	业务单据类型(1.进货订单，2.销货订单，3.入库单，4.出库，5.收款单，6.付款单，7.调拨单，8.零售单，9.零售退货单，10.销货退货，11.进货退货)
	 *@author yangguanghe [2014-6-18_下午5:36:45]
	 */
	public String createBCode(Integer oc, Byte btype) throws Exception {
		if (null == oc || null == btype) return null;
		
		Object bc = null;
		do {
			InvBillCodeConfig b = this.getByOc(oc);
			if (null == b) {
				
				// 先生成一条配置记录
				InvBillCodeConfig nb = new InvBillCodeConfig();
				nb.setOc(oc);
				if (RESULT.SUCCESS != super.add(nb))
					throw new RuntimeException("..保存单据配置记录失败..");
				
				// 保存单据计数器
				InvBillCode bcode = new InvBillCode();
				bcode.setBcc(nb.getCode());
				bcode.setBtype(btype);
				bcode.setYmd(new SimpleDateFormat(Sys.billCode_ymd).format(new Date())); // 这里保存的时间不用和配置的格式一样
				bcode.setNumber(1);
				if (RESULT.SUCCESS != super.add(bcode))
					throw new RuntimeException("..保存单据计数器失败..");
				
				// 返回单据编号
				String no = nb.getHead() + minus;
				no += DateUtils.getDateStr(DateUtils.getDateByStr(bcode.getYmd(), nb.getBody()), nb.getBody());
				no += this.getBuessByBtype(btype);
				no += nb.getOc();
				no += nb.getFoot().substring(0, nb.getFoot().length() - bcode.getNumber().toString().length());
				no += bcode.getNumber();
				return no;
			}
			
			// 查看是否有对应的业务计数
			List<Object> list = super.query(sql_createBillCode, null, 1, oc, btype);
			
			// 判断是否有对应业务的计数器
			if (null == list || list.size() == 0) {
				// 保存单据计数器
				InvBillCode bcode = new InvBillCode();
				bcode.setBcc(b.getCode());
				bcode.setBtype(btype);
				bcode.setYmd(new SimpleDateFormat(Sys.billCode_ymd).format(new Date())); // 这里保存的时间不用和配置的格式一样
				bcode.setNumber(1);
				if (RESULT.SUCCESS != super.add(bcode))
					throw new RuntimeException("..保存单据计数器失败..");
				
				// 返回单据编号
				String no = b.getHead() + minus;
				no += DateUtils.getDateStr(DateUtils.getDateByStr(bcode.getYmd(), b.getBody()), b.getBody());
				no += this.getBuessByBtype(btype);
				no += b.getOc();
				no += b.getFoot().substring(0, b.getFoot().length() - bcode.getNumber().toString().length());
				no += bcode.getNumber();
				return no;
			}
			
			if (null != list && list.size() > 0)
				bc = list.get(0);
			
		} while (null == bc);
		
		// b.head, b.body, b.foot, c.ymd, c.number, b.code as bcode, c.code as ccode, c.btype, b.oc
		Object[] dbbc = (Object[]) bc;
		String head = (null == dbbc[0]) ? Sys.NONE : dbbc[0].toString();
		String body = null == dbbc[1] ? Sys.NONE : dbbc[1].toString();
		String foot = null == dbbc[2] ? Sys.NONE : dbbc[2].toString();
		String ymd = null == dbbc[3] ? Sys.NONE : dbbc[3].toString();
		Integer number = null == dbbc[4] ? Sys.ONE : (Integer) dbbc[4];
		Integer ccode = null == dbbc[6] ? null : (Integer) dbbc[6];	// 计数器编号
		Byte type = null == dbbc[7] ? null : (Byte) dbbc[7];	// 业务类型
		Integer ocode = null == dbbc[8] ? null : (Integer) dbbc[8];	// 机构编号
		
		// 判断日期是否为同一天
		String nowDate = new SimpleDateFormat(Sys.billCode_ymd).format(new Date());
		if (!nowDate.equals(ymd)) {
			// 不是同一天，修改保存的日期，并初始化计数 number
			if (super.executeSql(sql_upd, nowDate, 1, ccode) == 0)
				throw new RuntimeException("..修改单据计数器失败..");
			
			String no = head + minus ;
			no += DateUtils.getDateStr(DateUtils.getDateByStr(nowDate, body), body);
			no += this.getBuessByBtype(type);
			no += ocode;
			no += foot.substring(0, foot.length() - 1);
			no += 1;
			
			return no;
		}
		
		// 修改计数器数量加 1
		if (super.executeSql(sql_upd, ymd, ++number, ccode) == 0)
			throw new RuntimeException("..修改单据计数器失败..");
		
		String no = head + minus ;
		no += DateUtils.getDateStr(DateUtils.getDateByStr(nowDate, body), body);
		no += this.getBuessByBtype(type);
		no += ocode;
		no += foot.substring(0, foot.length() - 1);
		no += number;
		return no;
	}
}
